package com.jcode.netty.protocol;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

/**
 * @Desc
 * @Author dreajay
 * @DateTime 2016年10月15日 上午10:24:04
 */
public class Packet implements Serializable {

    private static final long serialVersionUID = -318887462577783768L;

    /**
     * 客户端ID
     */
    private String clientId;

    /**
     * 包类型，0-请求、1-响应 、2-ONEWAY单向请求
     */
    private byte type;
    /**
     * 业务码
     */
    private int cmd;
    /**
     * 序列号 TODO 防止相同，分布式唯一 （客户端IP/MAC地址hash值-2位应用自增ID-时间戳/自增ID） ，服务端根据此去重
     */
    private long sequenceId;
    /**
     * 序列化类型
     */
    private byte serializeType;

    /**
     * 时间戳
     */
    private long timestamp;

    /**
     * 扩展属性
     */
    private Map<String, String> extFields = new HashMap<String, String>();

    /**
     * 报文体字节数组
     */
    private byte[] bodyData;

    /**
     * 报文体对象
     */
    private transient Serializable body;

    public Packet() {
    }

    public byte getType() {
        return type;
    }

    public void setType(byte type) {
        this.type = type;
    }

    public int getCmd() {
        return cmd;
    }

    public void setCmd(int cmd) {
        this.cmd = cmd;
    }

    public long getSequenceId() {
        return sequenceId;
    }

    public void setSequenceId(long sequenceId) {
        this.sequenceId = sequenceId;
    }

    public byte getSerializeType() {
        return serializeType;
    }

    public void setSerializeType(byte serializeType) {
        this.serializeType = serializeType;
    }

    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public Map<String, String> getExtFields() {
        return extFields;
    }

    public void setExtFields(Map<String, String> extFields) {
        this.extFields = extFields;
    }

    public void addExtField(String field, String value) {
        this.extFields.put(field, value);
    }

    public byte[] getBodyData() {
        return bodyData;
    }

    public void setBodyData(byte[] bodyData) {
        this.bodyData = bodyData;
    }

    public Serializable getBody() {
        return body;
    }

    public void setBody(Serializable body) {
        this.body = body;
    }

    public <T> T getBodyObject() {
        return (T)body;
    }

    public boolean isRequestType() {
        return PacketType.request.getValue() == type;
    }

    public boolean isResponseType() {
        return PacketType.response.getValue() == type;
    }

    public boolean isOnewayType() {
        return PacketType.oneway.getValue() == type;
    }

    public void markRequestType() {
        this.type = PacketType.request.getValue();
    }

    public void markResponseType() {
        this.type = PacketType.response.getValue();
    }

    public void markOnewayType() {
        this.type = PacketType.oneway.getValue();
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}
